#pragma once

struct empty_list_t{};

template<int data, typename tail>
struct list_t
{
   static const int head_ = data;
   typedef tail tail_;
};

template<typename list>
struct length
{
   static const size_t length_ = 1 + length<typename list::tail_>::length_;
};

template<>
struct length<empty_list_t>
{
   static const size_t length_ = 0;
};

template<size_t length, typename list>
struct prefix
{
   typedef list_t<list::head_, typename prefix<length - 1, typename list::tail_>::result_> result_;
};

template<typename list>
struct prefix<0, list>
{
   typedef empty_list_t result_;
};

template<size_t length, typename list>
struct suffix
{
   typedef typename suffix<length - 1, typename list::tail_>::result_ result_;
};

template<typename list>
struct suffix<0, list>
{
   typedef list result_;
};